﻿using System.Net;
using System.Net.Sockets;
using System;
using System.Text;
using System.Diagnostics;

namespace minimus
{
    public class GHostGameRequester
    {
        private struct udpheader
        {
            public ushort src_port;
            public ushort dest_port;
            public ushort length;
            public ushort checksum;
        };
        private static byte[] m_BroadcastCommand = Encoding.ASCII.GetBytes("rcon_broadcast");
        private Socket m_BroadcastRequester = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Udp);
        //private Socket m_BroadcastReceiver = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
        private BestDNSResolver m_Resolver;
        private byte[] GenerateBroadcastRequest()
        {
            udpheader h = new udpheader();
            h.dest_port = (ushort)m_Resolver.Port;
            h.src_port = 6112;
            h.length = (ushort)(8 + m_BroadcastCommand.Length);
            h.checksum = 0;
            byte[] data = new byte[h.length];
            Array.Copy(BitConverter.GetBytes(h.src_port), 0, data, 0, 2);
            Array.Copy(BitConverter.GetBytes(h.dest_port), 0, data, 2, 2);
            Array.Copy(BitConverter.GetBytes(h.length), 0, data, 4, 2);
            Array.Copy(BitConverter.GetBytes(h.checksum), 0, data, 6, 2);
            if (BitConverter.IsLittleEndian)
            {
                Array.Reverse(data, 0, 2);
                Array.Reverse(data, 2, 2);
                Array.Reverse(data, 4, 2);
                Array.Reverse(data, 6, 2);
            }
            Array.Copy(m_BroadcastCommand, 0, data, 8, m_BroadcastCommand.Length);
            return data;
        }
        byte[] m_RecvBuffer = new byte[512];

        public string RemoteServer
        {
            get
            {
                return m_Resolver.Host;
            }
            set
            {
                m_Resolver.Host = value;
            }
        }

        public int RemotePort
        {
            get
            {
                return m_Resolver.Port;
            }
            set
            {
                m_Resolver.Port = value;
            }
        }

        public GHostGameRequester(string host, int port)
        {
            m_Resolver = new BestDNSResolver(host, port);
            
            EndPoint ep = new IPEndPoint(IPAddress.Loopback, 6112);

            //m_BroadcastRequester.Rec
            //m_BroadcastRequester.ReceiveFrom(m_RecvBuffer, 256, 0, ref ep);

            //m_BroadcastRequester.BeginReceiveFrom(m_RecvBuffer, 0, m_RecvBuffer.Length, SocketFlags.Broadcast, ref ep, new AsyncCallback(ReadCallback), ep);
        }
        private void ReadCallback(IAsyncResult result)
        {
            EndPoint ep = result.AsyncState as EndPoint;
            int count = m_BroadcastRequester.EndReceiveFrom(result, ref ep);
            Debug.WriteLine("READ: " + Encoding.ASCII.GetString(m_RecvBuffer, 0, count));
        }
        public void RequestGames()
        {
            if (m_Resolver.GetBestIP() == null)
            {
                Trace.TraceWarning("No IP found for specified hostname");
                return;
            }
            try
            {
                m_BroadcastRequester.SendTo(GenerateBroadcastRequest(), m_Resolver.GetBestIP());
            }
            catch (SocketException ex)
            {
                Trace.TraceError(ex.ToString());
                m_Resolver.BestIPFailed();
            }
        }
    }
}